package frame.util.shiro;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.sql.*;
import java.util.HashSet;
import java.util.Set;

@Component
public class ShiroJdbc {
    //数据库配置属性
    @Value("${spring.datasource.driver-class-name}")
    private String driver;
    @Value("${spring.datasource.url}")
    private String url;
    @Value("${spring.datasource.username}")
    private String username;
    @Value("${spring.datasource.password}")
    private String password;


    @PostConstruct
    public void init() {
        System.out.println(String.format("ShiroJdbc读取：\n\tdriver=%s\n\turl=%s\n\tusername=%s\n\tpassword=%s",
                driver,url,username,password));
    }

    public Set<String> queryRolesByUsername(String username) {
        final Set<String> roles = new HashSet<>();
        String sql = "SELECT DISTINCT t.shiro FROM sys_role t JOIN sys_user_2_role r ON t.id = r.rid JOIN sys_user u ON u.id = r.uid WHERE u.username=? AND t.valid=1";
        this.query(sql, new Object[]{username}, (rs) -> {
            while (rs.next())
                roles.add(rs.getString(1));
        });
        return roles;
    }

    public Set<String> queryPermsByUsername(String username) {
        final Set<String> perms = new HashSet<>();
        String sql = "SELECT DISTINCT p.shiro FROM sys_user u JOIN sys_user_2_role ur ON ur.uid "
               + "JOIN sys_role_2_permission rp ON ur.rid=rp.rid "
               + "JOIN sys_permission p ON rp.pid=p.id "
               + "WHERE p.shiro!='' AND p.valid=1 AND u.username=?";
        this.query(sql, new Object[]{username}, (rs) -> {
            while (rs.next())
                perms.add(rs.getString(1));
        });
        return perms;
    }

    public void query(String sql, Object[] args,ResultSetHandle rsd) {
        Connection connection = null;
        PreparedStatement statement = null;
        ResultSet resultSet = null;

        try {
            Class.forName(driver);
            connection = DriverManager.getConnection(url, username, password);
            statement = connection.prepareStatement(sql);
            setArgs(statement, args);
            resultSet = statement.executeQuery();
            rsd.handle(resultSet);
        } catch (SQLException | ClassNotFoundException e) {
            e.printStackTrace();
        } finally {
            close(resultSet);
            close(statement);
            close(connection);
        }
    }

	public void logout(String username) {
		Connection connection = null;
        PreparedStatement statement = null;
        String sql = "UPDATE sys_user SET session_id=null,host=null WHERE username=?";
        try {
            Class.forName(driver);
            connection = DriverManager.getConnection(url, this.username, password);
            statement = connection.prepareStatement(sql);
            setArgs(statement, username);
            statement.executeUpdate();
        } catch (SQLException | ClassNotFoundException e) {
            e.printStackTrace();
        } finally {
            close(statement);
            close(connection);
        }

	}
    private void setArgs(PreparedStatement statement, Object... args) throws SQLException {
        if (statement == null) return;
        if (args == null || args.length == 0) return;
        for (int i = 0; i < args.length; i++) {
        	if (args[i] instanceof Integer) {
        		statement.setInt(i+1, (Integer)args[i]);
        	} else if (args[i] instanceof String) {
        		statement.setString(i+1, (String)args[i]);
        	} else {
        		statement.setObject(i+1, args[i]);
        	}
        }
    }
    // 关闭数据库
    private void close(Connection connection) {
        if (connection==null) return;
        try {
            connection.close();
        } catch (SQLException e) {
        }
    }
    // 关闭语句
    private void close(Statement statement) {
        if (statement==null) return;
        try {
            statement.close();
        } catch (SQLException e) {
        }
    }
    // 关闭结果集
    private void close(ResultSet resultSet) {
        if (resultSet==null) return;
        try {
            resultSet.close();
        } catch (SQLException e) {
        }
    }

    public static interface ResultSetHandle{
        void handle(ResultSet resultSet) throws SQLException;
    }


}
